<template>
    <div class="main-page-content page-demo-step" >
        <ContentHeader title="这里是用例点度量" explain="上传您的用例图，填写角色与用例的复杂程度，您将得到用例点度量结果"></ContentHeader>
        <div class="page-content">

            <span style="font-size: large;">上传您的用例图</span>
            <a-divider />
            <a-upload name="file" :multiple="false" :showUploadList="false" :customRequest="uploadUsecasePic"
                style="margin-left: 20px;">
                <a-button> <a-icon type="upload" /> 选择要上传的用例图（oom文件）</a-button>
            </a-upload>
            <div class="setDiv" v-if="uploadFlag == 1" style="margin-top: 20px;">
                <span style="font-size: large;">请填写对应角色个数</span>
                <a-divider />
                <a-card class="form-card" title="计算UAW">
                    <div class="no_inp">简单角色：<input type="number" v-model="simple_role" />个</div>
                    <div class="no_inp">普通角色：<input type="number" v-model="ordinary_role" />个 </div>
                    <div class="no_inp">复杂角色：<input type="number" v-model="complex_role" />个 </div>
                    <span style="float: right;">UAW为：{{ uaw }}</span><br />
                    <span v-if="role_check != true" style="color:red">请检查角色数目是否正确，图中角色数为{{ actors }}个</span>

                </a-card>
                <span style="font-size: large;">请填写对应用例个数</span>
                <a-divider />
                <a-card class="form-card" title="计算UUC">
                    <div class="no_inp">简单用例：<input type="number" v-model="simple_case" />个</div>
                    <div class="no_inp">普通用例：<input type="number" v-model="ordinary_case" />个 </div>
                    <div class="no_inp">复杂用例：<input type="number" v-model="complex_case" />个 </div>

                    <span style="float: right;">UUC为：{{ uuc }}</span><br />
                    <span v-if="case_check != true" style="color:red">请检查用例数目是否正确，图中用例数为{{ usecases }}个</span>
                </a-card>
                <div v-if="case_check && role_check == true">
                    <span style="font-size: large;">请填写对应技术复杂度等级</span>
                    <a-divider />
                    <a-card class="form-card" :loading="false" :bordered="false" title="计算TCF">
                        <template>
                            <a-table :columns="columns" :data-source="data" bordered :pagination="false"
                                style="width:900px;">
                                <template v-for="col in ['rank']" :slot="col" slot-scope="text, record, index">
                                    <div :key="col">
                                        <a-input v-if="record.editable" style="margin: -5px 0" :value="text"
                                            @change="e => handleChange(e.target.value, record.key, col)" />
                                        <template v-else>
                                            {{ text }}
                                        </template>
                                    </div>
                                </template>
                                <template slot="operation" slot-scope="text, record, index">
                                    <div class="editable-row-operations">
                                        <span v-if="record.editable">
                                            <a @click="() => save(record.key)">Save</a>
                                            <a-popconfirm title="Sure to cancel?" @confirm="() => cancel(record.key)">
                                                <a>Cancel</a>
                                            </a-popconfirm>
                                        </span>
                                        <span v-else>
                                            <a :disabled="editingKey !== ''" @click="() => edit(record.key)">Edit</a>
                                        </span>
                                    </div>
                                </template>
                            </a-table>
                            <br />
                            <span>当前TCF为：{{ tcf }}</span>

                        </template>
                    </a-card>
                    <span style="font-size: large;">请填写对应技术环境复杂度等级</span>
                    <a-divider />
                    <a-card class="form-card" :loading="false" :bordered="false" title="计算EF">
                        <template>
                            <a-table :columns="columns1" :data-source="data1" bordered :pagination="false"
                                style="width:900px;">
                                <template v-for="col in ['rank']" :slot="col" slot-scope="text, record, index">
                                    <div :key="col">
                                        <a-input v-if="record.editable" style="margin: -5px 0" :value="text"
                                            @change="e => handleChange(e.target.value, record.key, col)" />
                                        <template v-else>
                                            {{ text }}
                                        </template>
                                    </div>
                                </template>
                                <template slot="operation" slot-scope="text, record, index">
                                    <div class="editable-row-operations">
                                        <span v-if="record.editable">
                                            <a @click="() => save1(record.key)">Save</a>
                                            <a-popconfirm title="Sure to cancel?" @confirm="() => cancel1(record.key)">
                                                <a>Cancel</a>
                                            </a-popconfirm>
                                        </span>
                                        <span v-else>
                                            <a :disabled="editingKey1 !== ''" @click="() => edit1(record.key)">Edit</a>
                                        </span>
                                    </div>
                                </template>
                            </a-table>
                            <br />
                            <span>当前EF为：{{ ef }}</span>

                        </template>
                    </a-card>
                    <a-divider />
                    <span v-if="upc != 0" style="font-size: larger;font-weight: 1000;">本用例图用例点度量结果为：UPC = {{ upc }}</span>
                </div>
            </div>
            <div style="height:46px"></div>

        </div>
        <ContentFooter v-if="uploadFlag == 1" explain="用例点度量根据用例图中的角色和用例来对软件的规模进行度量">
            <div class="helpnote">
                <div>
                    1. 用例点的计算<br />
                    （1）未调整的角色权重UAW = 简单角色数量*1 + 普通角色数量*2 + 复杂角色*3<br />
                    （2）未调整前的用例权重UUC = 简单用例*5 + 普通用例*10 + 复杂用例*15<br />
                    （3）未调整前的用例点UUCP = UAW + UUC<br />
                    （4）技术复杂因子TCF = 0.6 + 0.01 * TFactor<br />
                    （5）环境因子EF = 1.4 + （-0.03 * EFactor）<br />
                    （6）调整后的用例点UPC = UUCP * TCF * EF<br />


                </div>
                <div>
                    2.评估用例复杂程度的方法有三种：<br />
                    （1）基于数据库实体的权重评估方法：通过分析用例中涉及的数据库实体数量来判断用例的复杂程度；<br />
                    （2）基于交互的权重评估方法：通过分析用例中包含的操作数量来判断用例的复杂程度；<br />
                    （3）基于分析类的权重评估方法：基于分析类的权重评估方法：通过分析实现用例的功能需要用到的类数量来判断用例的复杂程度。<br />

                </div>
            </div>
        </ContentFooter>
        <!-- <span v-if="actors != 0">actors: {{ actors }} useCases: {{ usecases }}</span> -->
        <ContentFooter v-else activeKey="1" explain="用例点度量根据用例图中的角色和用例来对软件的规模进行度量">
            <div class="helpnote">
                <div>
                    1. 用例点的计算<br />
                    （1）未调整的角色权重UAW = 简单角色数量*1 + 普通角色数量*2 + 复杂角色*3<br />
                    （2）未调整前的用例权重UUC = 简单用例*5 + 普通用例*10 + 复杂用例*15<br />
                    （3）未调整前的用例点UUCP = UAW + UUC<br />
                    （4）技术复杂因子TCF = 0.6 + 0.01 * TFactor<br />
                    （5）环境因子EF = 1.4 + （-0.03 * EFactor）<br />
                    （6）调整后的用例点UPC = UUCP * TCF * EF<br />


                </div>
                <div>
                    2.评估用例复杂程度的方法有三种：<br />
                    （1）基于数据库实体的权重评估方法：通过分析用例中涉及的数据库实体数量来判断用例的复杂程度；<br />
                    （2）基于交互的权重评估方法：通过分析用例中包含的操作数量来判断用例的复杂程度；<br />
                    （3）基于分析类的权重评估方法：基于分析类的权重评估方法：通过分析实现用例的功能需要用到的类数量来判断用例的复杂程度。<br />

                </div>
            </div>
        </ContentFooter>
        
    </div>
</template>

<script>
import ContentHeader from "@/components/content_header/content_header";
import ContentFooter from "@/components/content_footer/content_footer";
import Vue from 'vue'
import axios from 'axios'
Vue.prototype.$http = axios
const columns = [
    {
        title: '技术复杂性Ti',
        dataIndex: 'Tno',
        width: '16%',
        align: 'center',
        scopedSlots: { customRender: 'Tno' },
    },
    {
        title: '说明',
        dataIndex: 'explain',
        width: '30%',
        align: 'center',
        scopedSlots: { customRender: 'explain' },
    },
    {
        title: '权重',
        dataIndex: 'weight',
        align: 'center',
        width: '16%',
        scopedSlots: { customRender: 'weight' },
    },
    {
        title: '等级',
        dataIndex: 'rank',
        align: 'center',
        width: '16%',
        scopedSlots: { customRender: 'rank' },
    },
    {
        title: '操作',
        dataIndex: 'operation',
        align: 'center',
        scopedSlots: { customRender: 'operation' },
    },
];
const data = [];
const explainations = ['分布式系统', '响应或吞吐量性能', '终端用户效率', '复杂的内部处理', '代码必须重用', '易安装性', '易用性', '可移植性', '易更改性', '并发性', '特殊的安全性', '提供第三方接口', '需要特别的用户培训']
const weights = [2, 1, 1, 1, 1, 0.5, 0.5, 2, 1, 1, 1, 1, 1]
for (let i = 0; i < 13; i++) {
    data.push({
        key: i.toString(),
        Tno: 'T'.concat(i + 1),
        explain: explainations[i],
        weight: weights[i],
        rank: 3
    });
};
const columns1 = [
    {
        title: '环境复杂性Fi',
        dataIndex: 'Fno',
        width: '16%',
        align: 'center',
        scopedSlots: { customRender: 'Fno' },
    },
    {
        title: '说明',
        dataIndex: 'explain',
        width: '30%',
        align: 'center',
        scopedSlots: { customRender: 'explain' },
    },
    {
        title: '权重',
        dataIndex: 'weight',
        align: 'center',
        width: '16%',
        scopedSlots: { customRender: 'weight' },
    },
    {
        title: '等级',
        dataIndex: 'rank',
        align: 'center',
        width: '16%',
        scopedSlots: { customRender: 'rank' },
    },
    {
        title: '操作',
        dataIndex: 'operation',
        align: 'center',
        scopedSlots: { customRender: 'operation' },
    },
];
const data1 = [];
const explainations1 = ['熟悉UML程度', '开发应用程序的经验', '面对对象的经验', '主分析师能力', '激励机制', '需求稳定度', '具有兼职人员', '具有复杂编程']
const weights1 = [1.5, 0.5, 1, 0.5, 1, 2, -1, -1]
for (let i = 0; i < 8; i++) {
    data1.push({
        key: i.toString(),
        Fno: 'F'.concat(i + 1),
        explain: explainations1[i],
        weight: weights1[i],
        rank: 3
    });
};
export default {
    components: {
        ContentHeader,
        ContentFooter
    },
    data() {
        this.cacheData = data.map(item => ({ ...item }));
        this.cacheData1 = data1.map(item => ({ ...item }));
        return {
            actors: 0,
            usecases: 0,
            simple_role: 0,
            ordinary_role: 0,
            complex_role: 0,
            simple_case: 0,
            ordinary_case: 0,
            complex_case: 0,
            uploadFlag: 0,
            data,
            columns,
            editingKey: '',
            data1,
            columns1,
            editingKey1: ''
        }
    },
    computed: {
        uaw: function () {
            return Number(this.simple_role) * 1 + Number(this.ordinary_role) * 2 + Number(this.complex_role) * 3
        },
        uuc: function () {
            return Number(this.simple_case) * 5 + Number(this.ordinary_case) * 10 + Number(this.complex_case) * 15
        },
        role_check: function () {
            if (Number(this.simple_role) + Number(this.ordinary_role) + Number(this.complex_role) == Number(this.actors)) return true
            return false
        },
        case_check: function () {
            if (Number(this.simple_case) + Number(this.ordinary_case) + Number(this.complex_case) == Number(this.usecases)) return true
            return false
        },
        tcf: function () {
            let EFactor = 0;
            for (let i = 0; i < 8; i++) {
                EFactor = EFactor + Number(this.data1[i].rank) * Number(this.data1[i].weight)
            }
            return 1.4 - 0.03 * EFactor
        },
        ef: function () {
            let TFactor = 0;
            for (let i = 0; i < 13; i++) {
                TFactor = TFactor + Number(this.data[i].rank) * Number(this.data[i].weight)
            }
            return 0.6 + 0.01 * TFactor
        },
        upc: function () {
            let uucp = Number(this.uaw) + Number(this.uuc)
            return uucp * Number(this.tcf) * Number(this.ef)
        }
    },
    methods: {
        uploadUsecasePic(data) {
            let formdata = new FormData()
            formdata.append("file", data.file)
            console.log("上传用例图文件，发送HTTP请求……", data.file)
            this.$http.post('http://localhost:8085/scalemetric/usecase', formdata, {
                headers: {
                    'Content-Type': 'multipart/form-data; boundary = ' + new Date().getTime()
                }
            }
            ).then(res => {
                console.log("获取用例图信息，返回结果为：", res.data.data)
                this.actors = res.data.data.actors
                this.usecases = res.data.data.useCases
                this.uploadFlag = 1
            }).catch(error => {
                console.log(error)
            })
        },
        handleChange(value, key, column) {
            const newData = [...this.data];
            const target = newData.filter(item => key === item.key)[0];
            if (target) {
                target[column] = value;
                this.data = newData;
            }
        },
        edit(key) {
            const newData = [...this.data];
            const target = newData.filter(item => key === item.key)[0];
            this.editingKey = key;
            if (target) {
                target.editable = true;
                this.data = newData;
            }
        },
        save(key) {
            const newData = [...this.data];
            const newCacheData = [...this.cacheData];
            const target = newData.filter(item => key === item.key)[0];
            const targetCache = newCacheData.filter(item => key === item.key)[0];
            if (target && targetCache) {
                delete target.editable;
                this.data = newData;
                Object.assign(targetCache, target);
                this.cacheData = newCacheData;
            }
            this.editingKey = '';
        },
        cancel(key) {
            const newData = [...this.data];
            const target = newData.filter(item => key === item.key)[0];
            this.editingKey = '';
            if (target) {
                Object.assign(target, this.cacheData.filter(item => key === item.key)[0]);
                delete target.editable;
                this.data = newData;
            }
        },
        edit1(key) {
            const newData = [...this.data1];
            const target = newData.filter(item => key === item.key)[0];
            this.editingKey = key;
            if (target) {
                target.editable = true;
                this.data1 = newData;
            }
        },
        save1(key) {
            const newData = [...this.data1];
            const newCacheData = [...this.cacheData1];
            const target = newData.filter(item => key === item.key)[0];
            const targetCache = newCacheData.filter(item => key === item.key)[0];
            if (target && targetCache) {
                delete target.editable;
                this.data1 = newData;
                Object.assign(targetCache, target);
                this.cacheData1 = newCacheData;
            }
            this.editingKey = '';
        },
        cancel(key) {
            const newData = [...this.data1];
            const target = newData.filter(item => key === item.key)[0];
            this.editingKey = '';
            if (target) {
                Object.assign(target, this.cacheData1.filter(item => key === item.key)[0]);
                delete target.editable;
                this.data1 = newData;
            }
        }
    }

}
</script>


<style lang="less" scoped>
.editable-row-operations a {
    margin-right: 8px;
}

@import "./step.less";
</style>